package com.xinsoft.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.InOrOutStock;
import com.xinsoft.entity.dto.ScmPurchaseInstockParam;
import com.xinsoft.entity.dto.ScmPurchaseReturnDTO;
import com.xinsoft.entity.dto.ScmPurchaseReturnParam;
import com.xinsoft.entity.po.*;
import com.xinsoft.entity.vo.ScmPurchaseInstockPageVo;
import com.xinsoft.entity.vo.ScmPurchaseInstockVo;
import com.xinsoft.entity.vo.ScmPurchaseReturnPageVo;
import com.xinsoft.entity.vo.ScmPurchaseReturnVo;
import com.xinsoft.mapper.ScmPurchaseReturnItemMapper;
import com.xinsoft.service.ScmPurchaseReturnItemService;
import com.xinsoft.service.ScmPurchaseReturnService;
import com.xinsoft.mapper.ScmPurchaseReturnMapper;
import com.xinsoft.service.ScmStockService;
import com.xinsoft.service.SysDocumentNumService;
import com.xinsoft.utils.TokenUtil;
import lombok.Synchronized;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author ZYM
 * @description 针对表【scm_purchase_return(采购退货)】的数据库操作Service实现
 * @createDate 2023-07-27 14:15:43
 */
@Service
public class ScmPurchaseReturnServiceImpl extends ServiceImpl<ScmPurchaseReturnMapper, ScmPurchaseReturn>
        implements ScmPurchaseReturnService {

    @Resource
    private ScmPurchaseReturnItemMapper purchaseReturnItemMapper;
    @Autowired
    private ScmPurchaseReturnItemService purchaseReturnItemService;
    @Autowired
    private ScmStockService stockService;
    @Autowired
    private SysDocumentNumService sysDocumentNumService;

    @Override
    public IPage<ScmPurchaseReturnPageVo> findPageListByParam(ScmPurchaseReturnParam param) {
        Page<ScmPurchaseReturnPageVo> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        return baseMapper.findPageListByParam(page, param);
    }

    @Override
    public List<ScmPurchaseReturnPageVo> findListByParam(ScmPurchaseReturnParam param) {
        // IPage的参数 size<0 ，临时不分页
        Page<ScmPurchaseReturnPageVo> page = new Page<>(param.getCurrentPage(), -1);
        IPage<ScmPurchaseReturnPageVo> pageListByParam = baseMapper.findPageListByParam(page, param);
        return pageListByParam.getRecords();
    }

    @Override
    public Integer tempSave(ScmPurchaseReturnDTO dto) {
        ScmPurchaseReturn purchaseReturn = new ScmPurchaseReturn();
        BeanUtils.copyProperties(dto, purchaseReturn);
        purchaseReturn.setAuditStatus(Const.AUDIT_STATUS_WAIT);
        List<ScmPurchaseReturnItem> itemList = dto.getScmPurchaseReturnItemList();
        // 保存或新增
        if (Objects.isNull(purchaseReturn.getId())) {
            // 更新流水号
            sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.PURCHASE_RETURN_DOCUMENT);
            this.save(purchaseReturn);
        } else {
            purchaseReturnItemService.remove(Wrappers.lambdaQuery(ScmPurchaseReturnItem.class).eq(ScmPurchaseReturnItem::getPurchaseReturnId, purchaseReturn.getId()));
            this.updateById(purchaseReturn);
        }

        // 保存采购入库明细
        itemList.forEach(item -> {
            item.setPurchaseReturnId(purchaseReturn.getId());
            item.setSourceType(Const.ApproveType.CGRK);
        });
        purchaseReturnItemService.saveBatch(itemList);
        return purchaseReturn.getId();
    }

    @Override
    public ScmPurchaseReturnVo detail(Integer id) {
        ScmPurchaseReturnVo vo = baseMapper.getPurchaseReturnById(id);
        // 销售出库明细
        vo.setScmPurchaseReturnItemList(purchaseReturnItemMapper.listByPurchaseReturnId(id));
        return vo;
    }

    @Override
    public void del(List<Integer> ids) {
        List<ScmPurchaseReturn> list = this.list(Wrappers.lambdaQuery(ScmPurchaseReturn.class)
                .eq(ScmPurchaseReturn::getAuditStatus, Const.AUDIT_STATUS_NORMAL)
                .in(ScmPurchaseReturn::getId, ids));
        if (list.size() > 0) {
            throw new BDException("操作失败，只能删除未审核的采购退货单");
        }
        purchaseReturnItemService.remove(Wrappers.lambdaQuery(ScmPurchaseReturnItem.class).in(ScmPurchaseReturnItem::getPurchaseReturnId, ids));
        this.removeByIds(ids);
    }

    @Override
    public void audit(Integer id) {
        ScmPurchaseReturn purchaseReturn = this.getById(id);
        if (Const.AUDIT_STATUS_NORMAL.equals(purchaseReturn.getAuditStatus())) {
            throw new BDException("该单据已审核，无需重复审核");
        }
        this.update(Wrappers.lambdaUpdate(ScmPurchaseReturn.class)
                .eq(ScmPurchaseReturn::getId, id)
                .set(ScmPurchaseReturn::getAuditStatus, Const.AUDIT_STATUS_NORMAL)
                .set(ScmPurchaseReturn::getAuditId, TokenUtil.getUserId())
                .set(ScmPurchaseReturn::getAuditTime, new Date()));
        // 更新库存
        List<InOrOutStock> inOrOutStockList = this.getInOrOutStockList(id);
        stockService.updateInventory(Const.SourceBillType.CGTH, purchaseReturn.getReturnCode(), inOrOutStockList, Const.ChangeType.SUBTRACT);
    }

    @Override
    public void reverseAudit(Integer id) {
        ScmPurchaseReturn purchaseReturn = this.getById(id);
        if (Const.AUDIT_STATUS_WAIT.equals(purchaseReturn.getAuditStatus())) {
            throw new BDException("该单据未审核，无需反审核");
        }
        purchaseReturn.setAuditId(null);
        purchaseReturn.setAuditTime(null);
        purchaseReturn.setAuditStatus(Const.AUDIT_STATUS_WAIT);
        this.updateById(purchaseReturn);
        // 更新库存
        List<InOrOutStock> inOrOutStockList = this.getInOrOutStockList(id);
        stockService.updateInventory(Const.SourceBillType.CGTH, purchaseReturn.getReturnCode(), inOrOutStockList, Const.ChangeType.ADD);
    }

    /**
     * 获取出入库明细列表
     * @param id
     * @return {@link List}<{@link InOrOutStock}>
     */
    public List<InOrOutStock> getInOrOutStockList(Integer id) {
        List<InOrOutStock> list = new ArrayList<>();
        List<ScmPurchaseReturnItem> items = purchaseReturnItemService.list(Wrappers.lambdaQuery(ScmPurchaseReturnItem.class).eq(ScmPurchaseReturnItem::getPurchaseReturnId, id));
        items.forEach(item -> {
            InOrOutStock inOrOutStock = new InOrOutStock();
            BeanUtils.copyProperties(item,inOrOutStock);
            inOrOutStock.setQty(item.getReturnNum());
            list.add(inOrOutStock);
        });
        return list;
    }

    @Override
    public void addOrUpdateAudit(ScmPurchaseReturnDTO scmPurchaseReturnDTO) {
        Integer id = this.tempSave(scmPurchaseReturnDTO);
        this.audit(id);
    }

    @Override
    public void saveAudit(ScmPurchaseReturnDTO dto) {
        // 保存
        Integer id = this.tempSave(dto);
        // 审核
        this.audit(id);
    }
}



